package com.gobang.demo.api;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gobang.demo.game.Mather;
import com.gobang.demo.game.OnlineUserManager;
import com.gobang.demo.model.MatchRequest;
import com.gobang.demo.model.MatchResponse;
import com.gobang.demo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
@Slf4j
// 通过这个类来处理匹配功能中的 websocket 请求
public class MatchApi extends TextWebSocketHandler {

    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private Mather mather;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 1. 先获取到当前用户的身份信息(谁在游戏大厅中, 建立的连接)
        //    此处的代码, 之所以能够 getAttributes, 全靠了在注册 Websocket 的时候,
        //    加上的 .addInterceptors(new HttpSessionHandshakeInterceptor());
        //    这个逻辑就把 HttpSession 中的 Attribute 都给拿到 WebSocketSession 中了
        //    在 Http 登录逻辑中, 往 HttpSession 中存了 User 数据: httpSession.setAttribute("user", user);
        //    此时就可以在 WebSocketSession 中把之前 HttpSession 里存的 User 对象给拿到了.
        //    注意, 此处拿到的 user, 是有可能为空的!!
        //    如果之前用户压根就没有通过 HTTP 来进行登录, 直接就通过 /game_hall.html 这个 url 来访问游戏大厅页面
        //    此时就会出现 user 为 null 的情况
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
        // 要判断用户是否在线
        if (onlineUserManager.getFromGameHall(user.getUserId()) != null ||
            onlineUserManager.getFromGameRoom(user.getUserId()) != null) {
            MatchResponse response = new MatchResponse();
            response.setOk(true);
            response.setReason("账号已在别处登录");
            response.setMessage("repeatConnection");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        onlineUserManager.enterGameHall(user.getUserId(),session);
        log.info("玩家{}进入游戏大厅",user.getUserName());

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 玩家下线, 从 OnlineUserManager 中删除
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
        onlineUserManager.exitGameHall(user.getUserId());
        // 如果玩家正在匹配中, 而 websocket 连接断开了, 就应该移除匹配队列
        mather.remove(user);
        log.info("玩家{}退出游戏大厅",user.getUserName());

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            return;
            // 连接都关闭了，不能再发送了
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("用户未登录");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
        WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
        if (tmpSession == session) {
            onlineUserManager.exitGameHall(user.getUserId());
            log.info("玩家{}退出游戏大厅",user.getUserName());
        }
        // 如果玩家正在匹配中, 而 websocket 连接断开了, 就应该移除匹配队列
        mather.remove(user);
        log.info("玩家{}断开连接",user.getUserName());

    }
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 实现处理开始匹配请求和处理停止匹配请求.
        User user = (User) session.getAttributes().get("user");
        String payload = message.getPayload();
        MatchRequest request = objectMapper.readValue(payload, MatchRequest.class);
        MatchResponse response = new MatchResponse();
        // 根据前端发送过来的信息进行开始匹配或停止匹配
        if (request.getMessage().equals("startMatch")) {
            // 把玩家信息放入匹配队列之后, 就可以返回一个响应给客户端了.
            mather.add(user);
            response.setOk(true);
            response.setMessage("startMatch");
        }else if (request.getMessage().equals("stopMatch")) {
            // 退出匹配队列
            mather.remove(user);
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            response.setOk(false);
            response.setReason("非法的匹配请求");
        }
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
    }
}
